#include "../games/globale.h" // Fonction et Headers globaux
#include "../games/cls_configuration.h" // Classe de gestion du fichier de configuration
#include "../objects/cls_personnage.h" // objet du personnage

/* ----------------------------------------------------
			Constructeur
  ----------------------------------------------------- */
cls_Personnage::cls_Personnage()
{
    debugTrace("Constructeur cls_Personnage");

    // Initialisation des variables pour tous les personnages
    this->n_IndexSprite = 0;
    this->n_xVelocity = 0;
    this->n_yVelocity = 0;
    this->n_DirectionMovement = CST_PERSO_MOVE_PAUSE;

    // Initialisation de nextUpdateTime
    this->n_NextUpdateTime = 0;

}

/* ----------------------------------------------------
			Destructeur
  ----------------------------------------------------- */
cls_Personnage::~cls_Personnage()
{
    debugTrace("Destructeur cls_Personnage");
}

/* ----------------------------------------------------
			Retourne le prochain index du sprite
  ----------------------------------------------------- */
void cls_Personnage::fct_MoveStop()
{
    this->clsMap_Encours->fct_MoveStop();
    this->n_xVelocity = 0;
    this->n_DirectionMovement = CST_PERSO_MOVE_PAUSE;
}

/* ----------------------------------------------------
			Retourne le position en X et en Y
			ainsi que la taille de l'objet
  ----------------------------------------------------- */
    int cls_Personnage::fct_GetPosX() { return this->sdlR_PositionPerso_XY.x;}
    int cls_Personnage::fct_GetPosY() { return this->sdlR_PositionPerso_XY.y;}
    int cls_Personnage::fct_GetHeight() { return this->n_CST_SpriteHeight;}
    int cls_Personnage::fct_GetWidth() { return this->n_CST_SpriteWidth;}


/* ----------------------------------------------------
			Retourne le prochain index du sprite
  ----------------------------------------------------- */
int cls_Personnage::fct_NextSpriteIndex()
{
/*
    char toto[256];
    sprintf(toto, "%d", this->n_IndexSprite);
    debugTrace(toto);
*/
    // on incrémente l'index, si on dépasse le nombre maximun, on retourne au debut
    this->n_IndexSprite++;
    if (this->n_IndexSprite == this->n_CST_SpriteNumber) this->n_IndexSprite=0;

    return this->n_IndexSprite;
}



/* ----------------------------------------------------
			On initialise le sprite du personnage
  ----------------------------------------------------- */
void cls_Personnage::fct_InitPersonnage(cls_Map * clsMap_Encours, cls_PrimitiveTexte * clsPrimTexte_Dialogue, cls_Scenario* clsScenario, cls_Dialog* clsDialog, StrucPerso * paramPerso)
{
    int i;

    // Initialisation des variables selon le personnage
    this->clsMap_Encours = clsMap_Encours;
    this->clsPrimTexte_Dialogue = clsPrimTexte_Dialogue;
    this->n_CST_SpriteNumber = paramPerso->n_SpriteMouvement;
    this->n_CST_SpriteWidth = paramPerso->n_SpriteWidth;
    this->n_CST_SpriteHeight = paramPerso->n_SpriteHeight;
    this->n_CST_SpriteLeftBorder = paramPerso->n_SpriteLeftBorder;
    this->n_CST_SpriteRightBorder = paramPerso->n_SpriteRightBorder;
    this->n_CST_SpriteVelocity = paramPerso->n_SpriteVelocity;
    this->n_CST_SpriteDelay = paramPerso->n_SpriteDelay;

    this->clsDialog = clsDialog;
    this->clsScenario = clsScenario;
    this->paramPerso = paramPerso;

    // Position par defaut du personnage
    this->sdlR_PositionPerso_XY.x = paramPerso->n_DefaultX;
    this->sdlR_PositionPerso_XY.y = paramPerso->n_DefaultY;

    // Chargement du personnage en mouvement
    this->p_sdlS_SpritePerso = load_image(join_pathFile(PATH_DATA_IMG_CHARACTERS, paramPerso->st_SpriteNameMouvement));
    this->p_sdlR_positionSpriteGD = (SDL_Rect *)malloc(this->n_CST_SpriteNumber * sizeof (SDL_Rect));
    for (i = 0; i < this->n_CST_SpriteNumber; i++)
    {
        this->p_sdlR_positionSpriteGD[i].x = i * this->n_CST_SpriteWidth;
        this->p_sdlR_positionSpriteGD[i].y = 0;
        this->p_sdlR_positionSpriteGD[i].w = this->n_CST_SpriteWidth;
        this->p_sdlR_positionSpriteGD[i].h = this->n_CST_SpriteHeight;
    }
    this->p_sdlR_positionSpriteDG = (SDL_Rect *)malloc(this->n_CST_SpriteNumber * sizeof (SDL_Rect));
    for (i = 0; i < this->n_CST_SpriteNumber; i++)
    {
        this->p_sdlR_positionSpriteDG[i].x = i * this->n_CST_SpriteWidth;
        this->p_sdlR_positionSpriteDG[i].y = this->n_CST_SpriteHeight;
        this->p_sdlR_positionSpriteDG[i].w = this->n_CST_SpriteWidth;
        this->p_sdlR_positionSpriteDG[i].h = this->n_CST_SpriteHeight;
    }


    // Chargement du personnage en pause
    // Temporaire, car il n'y a qu'une image dans la pause
    this->p_sdlS_SpritePersoPause = load_image(join_pathFile(PATH_DATA_IMG_CHARACTERS, paramPerso->st_SpriteNameImmobile));
    this->sdlR_positionSpritePause[0].x = 0;
    this->sdlR_positionSpritePause[0].y = 0;
    this->sdlR_positionSpritePause[0].w = this->n_CST_SpriteWidth;
    this->sdlR_positionSpritePause[0].h = this->n_CST_SpriteHeight;

/*
    char stDebug[256];
    sprintf(stDebug, "INIT X = %d     ----    Y = %d", this->positionPerso_XY.x, this->positionPerso_XY.y);
    debugTrace(stDebug);
*/

}


/* ----------------------------------------------------
    Gestion des évènements
    On passe dans la fonction [fct_HandleInput] dans chaque classes : cls_map, cls_personnage, cls_object
  ----------------------------------------------------- */
void cls_Personnage::fct_HandleInput(SDL_Event event)
{
    if (event.type == SDL_MOUSEBUTTONUP)
    {
        switch (event.button.button)
        {

            case SDL_BUTTON_LEFT:
                // On sauve la position en X demandé
                this->sdlR_DestinationPerso_XY.x = event.button.x;

                // On détermine si l'on a demandé
                if (this->sdlR_PositionPerso_XY.x > this->sdlR_DestinationPerso_XY.x - this->n_CST_SpriteLeftBorder)
                {
                    // un deplacement à gauche
                    this->n_DirectionMovement = CST_PERSO_MOVE_LEFT;
                    // On indique la valeur de déplacement
                    this->n_xVelocity = - this->n_CST_SpriteVelocity;
                }
                else if (this->sdlR_PositionPerso_XY.x < this->sdlR_DestinationPerso_XY.x - this->n_CST_SpriteRightBorder)
                {
                    // un deplacement à droite
                    this->n_DirectionMovement = CST_PERSO_MOVE_RIGHT;
                    // On indique la valeur de déplacement
                    this->n_xVelocity = this->n_CST_SpriteVelocity;
                }
                break;

            case SDL_BUTTON_MIDDLE:
                break;

            case SDL_BUTTON_RIGHT:
                // Le bouton droit arrete le déplacement du personnage (et du décors)
                this->fct_MoveStop();
                break;

            default: break;
        }
    }

}



/* ----------------------------------------------------
			On Dessine le personnage au bon endroit
  ----------------------------------------------------- */
int cls_Personnage::fct_DrawPerso(SDL_Surface *p_sdlS_Ecran, int n_CurrentTime)
{

    int valNextSpriteIndex;

    /* ----------------------------- */
    // Si on a dépassé la "date" de mise à jour du sprite, on passe à l'étape suivante de l'animation
    if(n_CurrentTime > this->n_NextUpdateTime)
    {
        // Si le personnage est en mouvement et a atteind l'endroit désiré, on arrête son déplacement
        if ((this->n_DirectionMovement == CST_PERSO_MOVE_RIGHT && this->sdlR_PositionPerso_XY.x > (this->sdlR_DestinationPerso_XY.x - this->n_CST_SpriteRightBorder))
         || (this->n_DirectionMovement == CST_PERSO_MOVE_LEFT && this->sdlR_PositionPerso_XY.x < (this->sdlR_DestinationPerso_XY.x - this->n_CST_SpriteLeftBorder)))
        {
            this->fct_MoveStop();
        }
        else
        {
            switch(this->n_DirectionMovement)
            {
                case CST_PERSO_MOVE_RIGHT:
                    // Si le personnage arrive du le bord Droit de la fenêtre, on donne de la vitesse au decors
                    if (this->sdlR_PositionPerso_XY.x + n_CST_SpriteRightBorder + 50 > cls_Configuration::getWindowWidth() - CST_LIMTE_MOVE_MAP )
                    {
                        if (this->clsMap_Encours->fct_IsMovePossible(CST_PERSO_MOVE_RIGHT))
                        {
                            if (this->clsMap_Encours->fct_MoveRightStart() == false)
                            {
                                // Si l'image de fond n'était pas en mouvement,
                                // on redessine le personnage dans son ancienne position
                                //SDL_BlitSurface(this->p_sdlS_SpritePerso, &this->p_sdlR_positionSpriteGD[this->n_IndexSprite], p_sdlS_Ecran, &this->sdlR_PositionPerso_XY);
                                //return;
                                return REDRAW_ALL;
                            }
                        }
                        else
                        {
                            // On arrive à l'extrême droite du decors
                            this->fct_MoveStop();
                            this->clsPrimTexte_Dialogue->fct_DefineTexte("Je ne peux pas aller plus loin !!", n_CurrentTime + 2500);
                            //this->fct_PlaySound(); // On joue le son
                        }
                    }
                    else
                    {
                        this->clsMap_Encours->fct_MoveStop();
                    }

                    break;

                case CST_PERSO_MOVE_LEFT:
                    // Si le personnage arrive sur le bord Gauche de la fenêtre, on donne de la vitesse au decors
                    if (this->sdlR_PositionPerso_XY.x < CST_LIMTE_MOVE_MAP)
                    {
                        if (this->clsMap_Encours->fct_IsMovePossible(CST_PERSO_MOVE_LEFT))
                        {
                            if (this->clsMap_Encours->fct_MoveLeftStart() == false)
                            {
                                // Si l'image de fond n'etait pas en mouvement,
                                // on redessine le personnage dans son ancienne position
                                //SDL_BlitSurface(this->p_sdlS_SpritePerso, &this->p_sdlR_positionSpriteDG[this->n_IndexSprite], p_sdlS_Ecran, &this->sdlR_PositionPerso_XY);
                                return REDRAW_ALL;
                            }
                        }
                        else
                        {
                            // On arrive à l'extrême gauche du decors
                            this->fct_MoveStop(); // On arrête tout
                            this->clsPrimTexte_Dialogue->fct_DefineTexte("Je ne peux pas aller plus loin !!", n_CurrentTime + 2500);
                            //this->fct_PlaySound(); // On joue le son
                        }
                    }
                    else
                    {

                        this->clsMap_Encours->fct_MoveStop();

                    }

                    break;
            }
        }

        // Si la vitesse n'est pas nulle, on fait une translation du personnage
        this->sdlR_PositionPerso_XY.x += this->n_xVelocity;
        this->sdlR_PositionPerso_XY.y += this->n_yVelocity;
        valNextSpriteIndex = this->fct_NextSpriteIndex();

        // Gestion du décalage de l'image de fond,
        // en enlevant au personnage la vitesse de defilement du fond
        this->sdlR_PositionPerso_XY.x -= this->clsMap_Encours->n_xVelocity;
        // On fixe la date du prochain changement : une demi seconde après
        this->n_NextUpdateTime = n_CurrentTime + this->n_CST_SpriteDelay;

        //debugTrace("Destructeur cls_Objet");
        //debugTrace("FRAMEREATE |||||||||| OUI");
    }
    // Sinon on reste sur le dernier index du sprite
    else
    {
        valNextSpriteIndex = this->n_IndexSprite;
        //debugTrace("FRAMEREATE --------- NON");
    }

    // Affiche le bon élément selon le mouvement et l'index du sprite
    switch(this->n_DirectionMovement)
    {
        case CST_PERSO_MOVE_PAUSE:
            SDL_BlitSurface(this->p_sdlS_SpritePersoPause, &this->sdlR_positionSpritePause[0], p_sdlS_Ecran, &this->sdlR_PositionPerso_XY);
            break;

        case CST_PERSO_MOVE_RIGHT:
            SDL_BlitSurface(this->p_sdlS_SpritePerso, &this->p_sdlR_positionSpriteGD[valNextSpriteIndex], p_sdlS_Ecran, &this->sdlR_PositionPerso_XY);
            break;

        case CST_PERSO_MOVE_LEFT:
            SDL_BlitSurface(this->p_sdlS_SpritePerso, &this->p_sdlR_positionSpriteDG[valNextSpriteIndex], p_sdlS_Ecran, &this->sdlR_PositionPerso_XY);
            break;
    }

    return RETOK;
}

/* ----------------------------------------------------
			On libere les surfaces
  ----------------------------------------------------- */
void cls_Personnage::fct_FreeSurface()
{
    SDL_FreeSurface(this->p_sdlS_SpritePerso);
    SDL_FreeSurface(this->p_sdlS_SpritePersoPause);


    free(this->p_sdlR_positionSpriteGD);
    free(this->p_sdlR_positionSpriteDG);
/*
    // Joda du 15/01/2008
    free(this->clsMap_Encours);
    free(this->clsPrimTexte_Dialogue);
*/
}
